package cn.uncode.rpc.transport.netty.server;

import cn.uncode.rpc.common.CommonConstant;
import cn.uncode.rpc.core.URL;
import cn.uncode.rpc.core.URLParam;
import cn.uncode.rpc.spi.ExtensionLoader;
import cn.uncode.rpc.transport.NettyChannelBuilder;
import cn.uncode.rpc.transport.RequestHandler;
import cn.uncode.rpc.util.StandardThreadExecutor;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;


public class NettyServerChannelInitializer extends ChannelInitializer<SocketChannel> {
	
	private StandardThreadExecutor standardThreadExecutor;
	private RequestHandler requestHandler;
	
	public NettyServerChannelInitializer(URL url, RequestHandler requestHandler){
		this.requestHandler = requestHandler;
		boolean shareChannel = url.getBooleanParameter(URLParam.SHARE_CHANNEL.getName(),
				URLParam.SHARE_CHANNEL.getBooleanValue());
		int workerQueueSize = url.getIntParameter(URLParam.WORKER_QUEUE_SIZE.getName(),
				URLParam.WORKER_QUEUE_SIZE.getIntValue());

		int minWorkerThread = 0, maxWorkerThread = 0;

		if (shareChannel) {
			minWorkerThread = url.getIntParameter(URLParam.MIN_WORKER_THREAD.getName(),
					CommonConstant.NETTY_SHARECHANNEL_MIN_WORKDER);
			maxWorkerThread = url.getIntParameter(URLParam.MAX_WORDER_THREAD.getName(),
					CommonConstant.NETTY_SHARECHANNEL_MAX_WORKDER);
		} else {
			minWorkerThread = url.getIntParameter(URLParam.MIN_WORKER_THREAD.getName(),
					CommonConstant.NETTY_NOT_SHARECHANNEL_MIN_WORKDER);
			maxWorkerThread = url.getIntParameter(URLParam.MAX_WORDER_THREAD.getName(),
					CommonConstant.NETTY_NOT_SHARECHANNEL_MAX_WORKDER);
		}

		standardThreadExecutor = (standardThreadExecutor != null && !standardThreadExecutor.isShutdown()) ? standardThreadExecutor
				: new StandardThreadExecutor(minWorkerThread, maxWorkerThread, workerQueueSize,
						new DefaultThreadFactory("NettyServer-" + url.getServerPortStr(), true));
		standardThreadExecutor.prestartAllCoreThreads();
	}


    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        NettyChannelBuilder nettyChannelBuilder = ExtensionLoader.getExtensionLoader(NettyChannelBuilder.class).getExtension(CommonConstant.DEFAULT_VALUE);
        nettyChannelBuilder.buildServer(standardThreadExecutor, requestHandler, pipeline);
    }
}
